package com.yj.timecapsule.service.sms;

import cn.hutool.core.util.RandomUtil;
import com.yj.timecapsule.common.constant.SmsCodeStatus;
import com.yj.timecapsule.common.enums.ErrorCode;
import com.yj.timecapsule.common.error.BusinessException;
import com.yj.timecapsule.common.utils.AsyncTaskUtil;
import com.yj.timecapsule.common.utils.PhoneNumberValidator;
import com.yj.timecapsule.common.utils.SmsUtil;
import com.yj.timecapsule.entity.SmsCode;
import com.yj.timecapsule.mapper.SmsCodeMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SmsService {
    @Resource
    private SmsCodeMapper smsCodeMapper;
    @Resource
    private ThreadPoolTaskExecutor smsExecutor;

    public void sendCode(String phone) {
        PhoneNumberValidator.valid(phone);
        Date now = new Date();
        List<SmsCode> smsCodeList = smsCodeMapper.selectByPhone(phone);
        if (!smsCodeList.isEmpty()) {
            SmsCode smsCode = smsCodeList.get(0);
            Date createAt = smsCode.getCreateAt();
            if (isWithinOneMinute(createAt, now)) {
                throw new BusinessException(ErrorCode.SEND_MESSAGE_TOO_FREQUENT);
            }
        }
        AsyncTaskUtil.runAsync(() -> {
            log.info("处理短信发送业务，当前线程:{}", Thread.currentThread().getName());
            String code = generatorCode();
            SmsCode smsCode = new SmsCode();
            smsCode.setCreateAt(now);
            smsCode.setPhone(phone);
            smsCode.setCode(code);
            smsCode.setUse(SmsCodeStatus.NOT_USE);
            SmsUtil.sendCode(phone, code);
            smsCodeMapper.insertSelective(smsCode);
        }, smsExecutor);
//        CompletableFuture.runAsync(() -> {
//            log.info("处理短信发送业务，当前线程:{}",Thread.currentThread().getName());
//            String code = generatorCode();
//            SmsCode smsCode = new SmsCode();
//            smsCode.setCreateAt(now);
//            smsCode.setPhone(phone);
//            smsCode.setCode(code);
//            smsCode.setUse(SmsCodeStatus.NOT_USE);
//            SmsUtil.sendCode(phone, code);
//            smsCodeMapper.insertSelective(smsCode);
//        },smsExecutor);

    }


    private boolean isWithinOneMinute(Date date1, Date date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);

        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);

        return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR)
                && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH)
                && calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH)
                && calendar1.get(Calendar.HOUR_OF_DAY) == calendar2.get(Calendar.HOUR_OF_DAY)
                && calendar1.get(Calendar.MINUTE) == calendar2.get(Calendar.MINUTE);
    }

    private String generatorCode() {
        return RandomUtil.randomNumbers(4);
    }

    public void verifyCode(String phone, String code) {
        PhoneNumberValidator.valid(phone);
        // 5分钟内有效
        List<SmsCode> smsCodeList = smsCodeMapper.selectByPhone(phone);
        if (!smsCodeList.isEmpty()) {
            SmsCode smsCode = smsCodeList.get(0);
            // 判断是否过期
            Date createdAt = smsCode.getCreateAt();
            long minutesSinceCreation = TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis() - createdAt.getTime());
            if (minutesSinceCreation > 5) {
                throw new BusinessException(ErrorCode.SMS_CODE_ERROR);
            }
            //校验验证码
            if (!smsCode.getCode().equals(code)) {
                throw new BusinessException(ErrorCode.SMS_CODE_ERROR);
            }
            smsCode.setUse(SmsCodeStatus.IS_USE);
            smsCodeMapper.updateByPrimaryKeySelective(smsCode);
            log.info("验证码校验成功,{}", phone);
        } else {
            // TODO 节省短信资源。。 测试时先注释掉
            // throw new BusinessException(ErrorCode.SMS_CODE_ERROR);
        }


    }
}
